using JT808Protocol.Models.BodyParserStrategy.Location;
using JT808Protocol.Models.BodyParserStrategy.Location.LocationAddition;
using JT808Protocol.Models.Enums;
using JT808Protocol.Models.JsonConverters;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace JT808Protocol.Models
{
    /// <summary>
    /// 消息头解析
    /// </summary>
    public interface IJT808Header
    {
        /// <summary>
        /// 消息头解析
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="startIndex">起始位置</param>
        /// <returns></returns>
        IJT808Header ReadHeader(ReadOnlySpan<byte> data, ref int index);

        /// <summary>
        /// 获取消息头字节
        /// </summary>
        /// <returns></returns>
        List<byte> WriteToBytes();
    }

    /// <summary>
    /// 消息体解析
    /// </summary>
    [JsonConverter(typeof(MsgBodyHumanizeConverter))]
    public abstract class IJT808Body
    {
        /// <summary>
        /// 消息头上下文，消息体解析过程可能使用
        /// </summary>
        protected JT808Header HeaderContext { get; set; }

        /// <summary>
        /// 设置消息头上下文
        /// </summary>
        /// <param name="header"></param>
        public void SetHeaderContext(JT808Header header)
        {
            this.HeaderContext = header;
        }

        /// <summary>
        /// 返回消息头上下文
        /// </summary>
        /// <returns></returns>
        public JT808Header GetHeaderContext()
        {
            return this.HeaderContext;
        }

        /// <summary>
        /// 消息体解析
        /// </summary>
        /// <param name="data">原始数据</param>
        /// <param name="startIndex">起始位置</param>
        /// <returns></returns>
        public abstract IJT808Body ReadBody(ReadOnlySpan<byte> data, ref int index);

        /// <summary>
        /// 获取消息体字节
        /// </summary>
        /// <returns></returns>
        public abstract List<byte> WriteToBytes();
    }

    /// <summary>
    /// 位置附加信息解析
    /// </summary>
    [JsonConverter(typeof(LocationAdditionConverter))]
    public abstract class ILocationAddition
    {
        /// <summary>
        /// 附加信息ID
        /// </summary>
        [JsonPropertyName("附加信息类型")] public EnumLocationAddition AdditionID { get; set; }

        /// <summary>
        /// 附加信息总长度(等于1+1+[n]字节)
        /// </summary>
        [JsonPropertyName("附加信息长度")] public byte DataLength { get; set; }

        /// <summary>
        /// 报警标识号
        /// </summary>
        [JsonPropertyName("报警标识号")] public AlarmLogo AlarmLogo { get; set; }

        public abstract ILocationAddition ReadEntity(ReadOnlySpan<byte> source, int startIndex);
    }

    /// <summary>
    /// 设备参数接口,平台既要读取，也要设定
    /// 由于长度是 byte，与 body 的长度 uint16 不一样，所以另行定义接口
    /// </summary>
    public interface IDeviceParam
    {
        /// <summary>
        /// 参数ID
        /// </summary>
        uint ParamID { get; }

        /// <summary>
        /// 数据总长度
        /// </summary>
        byte Length { get; }

        /// <summary>
        /// 参数类型
        /// </summary>
        EnumDeviceParamType ParamType { get; }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        List<byte> WriteToNetBytes();

        /// <summary>
        /// 从指定位置解析数据
        /// </summary>
        /// <param name="source"></param>
        /// <param name="startIndex"></param>
        /// <returns></returns>
        void ReadEntity(ref ReadOnlySpan<byte> source, ref int startIndex);
    }
}